#include "StdAfx.h"

#include "resource.h"
#include "Charplan.h"
#include <direct.h>

#include "dep/sqlite/sqlite3.h"

using namespace std;


CDBInterfaceSQL gdbinterface;



CDBInterfaceSQL::CDBInterfaceSQL(void)
{
    mp_db = NULL;
    mb_suspend_sql_error = false;
    sqlite3_initialize();
	Reset();
}


CDBInterfaceSQL::~CDBInterfaceSQL(void)
{
    DeleteContents();
    sqlite3_shutdown();
}


//////////////////////////////////////////////////////////////////////////
void    CDBInterfaceSQL::DeleteContents()
{
    if (mp_db)
    {
        int res = sqlite3_close(mp_db);
        ASSERT(res == SQLITE_OK);
        mp_db = NULL;
    }
}


//////////////////////////////////////////////////////////////////////////
#ifdef ONLY_US_DB
bool	CDBInterfaceSQL::Init(const TCHAR* language)
{
    mstr_current_language = language;

    if (!mp_db)
    {
        CString path = ((CCharplanApp*)AfxGetApp())->GetDataPath() + CString("data_us");

        int res = sqlite3_open_v2(path,&mp_db, SQLITE_OPEN_NOMUTEX|SQLITE_OPEN_READONLY ,NULL);
        ASSERT(res == SQLITE_OK);

        if (res != SQLITE_OK) 
        {
            CString errtext;
            errtext.Format("Error %i: %s",sqlite3_errcode(mp_db),sqlite3_errmsg(mp_db));
            TRACE(errtext);
            MessageBox(NULL, errtext,_T("Charplan-Error"),MB_OK);
            return false;
        }
    }

	return true;
}
#else
bool	CDBInterfaceSQL::Init(const TCHAR* language, bool old_version)
{

    if (mb_old_version != old_version)
    {
        DeleteContents();
    }

    mstr_current_language = language;
    mb_old_version = old_version;


    if (!mp_db)
    {
        CString path = ((CCharplanApp*)AfxGetApp())->GetDataPath();
        if (mb_old_version) path += CString("data_eu");
        else                path += CString("data_us");

        int res = sqlite3_open_v2(path,&mp_db, SQLITE_OPEN_NOMUTEX|SQLITE_OPEN_READONLY ,NULL);
        ASSERT(res == SQLITE_OK);

        if (res != SQLITE_OK) 
        {
            CString errtext;
            errtext.Format("Error %i: %s",sqlite3_errcode(mp_db),sqlite3_errmsg(mp_db));
            TRACE(errtext);
            MessageBox(NULL, errtext,_T("Charplan-Error"),MB_OK);
            return false;
        }
    }

	return true;
}
#endif

//////////////////////////////////////////////////////////////////////////
bool   CDBInterfaceSQL::CreateMemoryCopy()
{
    CString path = ((CCharplanApp*)AfxGetApp())->GetDataPath();
    CString path2 = path + "data_temp";
#ifdef ONLY_US_DB
    path += CString("data_us");
#else
    if (mb_old_version) path += CString("data_eu");
    else                path += CString("data_us");
#endif

    CopyFile(path,path2,FALSE);

    sqlite3*    new_db;
    int sres = sqlite3_open_v2(path2,&new_db, SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_READWRITE,NULL);
    ASSERT(sres == SQLITE_OK);
    if (sres != SQLITE_OK) return false;
   
    if (mp_db)   sqlite3_close(mp_db);
    mp_db = new_db;

    return true;
}




//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::Reset()
{
	mn_selected_realm = -1;
	m_class.id = -1;
	mn_selected_race = -1;
	mn_selected_styleline = -1;
	mn_selected_style = -1;
	mn_selected_spellline = -1;
	mn_selected_spellcat = -1;
	mn_selected_spell = -1;
	mn_selected_ra = -1;
	mn_selected_raNF = -1;
	mn_selected_mastertrack = -1;
}




CString CDBInterfaceSQL::sqlite3_escape_string(const CString& input)
{
    CString res = input;
    res.Replace("\'","\'\'");
    return res;
}

bool    CDBInterfaceSQL::sql_CheckForError(int res, int expected /*= SQLITE_OK*/)
{
    if (res != expected)
    {
        CString errtext;
        errtext.Format("SQL-Error %i: %s",sqlite3_errcode(mp_db),sqlite3_errmsg(mp_db));
        TRACE(errtext+"\n");

        if (!mb_suspend_sql_error)
        {
            int dlgres = MessageBox(NULL, errtext+_T("\r\n\r\nSuspend these error messages?"),_T("Charplan-Error"),MB_YESNO);
            if (dlgres==IDYES)  mb_suspend_sql_error = true;
        }
    }
    ASSERT(res == expected);

    return res!=expected;
}


//////////////////////////////////////////////////////////////////////////
sqlite3_stmt*     CDBInterfaceSQL::sql_prepare(const char* pszFormat,...)
{
    ASSERT(mp_db);

    char command[1024];
    va_list argptr;
    va_start(argptr, pszFormat);
    vsprintf_s(command,1024,pszFormat,argptr);
    va_end(argptr);

    #ifdef _DEBUG
/*    FILE*outf;
    if (!fopen_s(&outf,"SQL_log.txt","at"))
    {
        fprintf(outf,command);
        fprintf(outf,"\n");
        fclose(outf);
    }
*/
    #endif


    sqlite3_stmt* plineInfo = NULL;
    int res = sqlite3_prepare_v2(mp_db, command, -1, &plineInfo, 0); 

    if (sql_CheckForError(res))
    {
        plineInfo = NULL;
    }

    
    return plineInfo;
}

//////////////////////////////////////////////////////////////////////////
bool     CDBInterfaceSQL::sql_execute(const char* pszFormat,...)
{
    ASSERT(mp_db);

    char command[1024];
    va_list argptr;
    va_start(argptr, pszFormat);
    vsprintf_s(command,1024,pszFormat,argptr);
    va_end(argptr);


    sqlite3_stmt* plineInfo = NULL;
    int res = sqlite3_prepare_v2(mp_db, command, -1, &plineInfo, 0); 

    if (sql_CheckForError(res))
    {
        plineInfo = NULL;
        return false;
    }


    res = sqlite3_step(plineInfo);
    if (sql_CheckForError(res, SQLITE_DONE))
    {
        sqlite3_finalize(plineInfo); 
        plineInfo = NULL;
        return false;
    }

    sqlite3_finalize(plineInfo); 
    return true;
}



//////////////////////////////////////////////////////////////////////////
const char*  CDBInterfaceSQL::sql_table_langEN_DE()
{
    if (mstr_current_language=="de")            return "_DE";
    ASSERT(mstr_current_language=="en" || mstr_current_language=="fr");
    return "_EN";
}

const char*  CDBInterfaceSQL::sql_table_langEN_DE_FR()
{
    if (mstr_current_language=="de")            return "_DE";
    if (mstr_current_language=="fr")            return "_FR";
    ASSERT(mstr_current_language=="en");
    return "_EN";
}


const char*  CDBInterfaceSQL::langEN_DE_FR()
{
    if (mstr_current_language=="de")            return "DE";
    if (mstr_current_language=="fr")            return "FR";
    ASSERT(mstr_current_language=="en");
    return "EN";
}


//////////////////////////////////////////////////////////////////////////
CString CDBInterfaceSQL::sql_table_field_no_tab(const CString& table, const CString& field)
{
    ASSERT(table.Left(1)>="A" && table.Left(1)<="Z");
    ASSERT(field.Left(1)>="A" && field.Left(1)<="Z");

    CString res = field;

    // TODO: change db layout for a unique way
    if (table=="Classes" && field=="Name")          res += sql_table_langEN_DE_FR();    else
    if (table=="Race" && field=="Name")             res += sql_table_langEN_DE_FR();    else
    if (table=="Stylelines" && field=="Name")       res += sql_table_langEN_DE();       else
    if (table=="Styles" && field=="Name")           res += sql_table_langEN_DE();       else
    if (table=="Styles" && field=="Fatigue_Cost")   res += sql_table_langEN_DE();       else
    if (table=="Styles" && field=="Effect")         res += sql_table_langEN_DE();       else
    if (table=="Spelllines" && field=="SPEC_Name")  res += sql_table_langEN_DE();       else
    if (table=="Spelllines" && field=="Name_Base")  res += sql_table_langEN_DE();       else
    if (table=="Spelllines" && field=="Name_Spec")  res += sql_table_langEN_DE();       else
    if (table=="Spellcat" && field=="Name")         res += sql_table_langEN_DE();       else
    if (table=="Spells" && field=="Name")           res += sql_table_langEN_DE();       else
    if (table=="Spells" && field=="Effect")         res += sql_table_langEN_DE();       else
    if (table=="Spellcat_descriptio" && field=="Text")   res += sql_table_langEN_DE();  else
    if (table=="Styles_Open_Pos" && field=="Name")  res += sql_table_langEN_DE();       else
    if (table=="Styles_Open_Result" && field=="Name")  res += sql_table_langEN_DE();       else
    if (table=="Styles_Defense_Bonu" && field=="Name")  res += sql_table_langEN_DE();       else
    if (table=="Styles_Bonus" && field=="Name")    res += sql_table_langEN_DE();       else
    if (table=="Ability_Desc" && field=="Name")    res += sql_table_langEN_DE();       else
    if (table=="Ability_Desc" && field=="Desc")    res += sql_table_langEN_DE();       else
    if (table=="Rasnf" && field=="Name")           res += sql_table_langEN_DE_FR();       else
    if (table=="Rasnf" && field=="TEXT")           res += sql_table_langEN_DE_FR();       else
    if (table=="Targets" && field=="Name")         res += sql_table_langEN_DE();       else
    if (table=="Spells_Resi" && field=="Name")     res += sql_table_langEN_DE();       else
    if (table=="MasterQuest" && field=="Name")     res += sql_table_langEN_DE_FR();       else
    if (table=="Masterlines" && field=="Name")     res += sql_table_langEN_DE_FR();       else
    if (table=="Masterlevel" && field=="L_Name")   res += sql_table_langEN_DE_FR();       else
    if (table=="Masterlevel" && field=="Description")   res += sql_table_langEN_DE_FR();       else
    if (table=="Base_Classes" && field=="Base_Name")     res += sql_table_langEN_DE_FR();       else
    if (table=="ChampSpells" && field=="Name")     res += sql_table_langEN_DE_FR();       else
    if (table=="ChampSpells" && field=="L1")     res += sql_table_langEN_DE_FR();       else
    if (table=="ChampSpells" && field=="L2")     res += sql_table_langEN_DE_FR();       else
    if (table=="ChampSpells" && field=="L3")     res += sql_table_langEN_DE_FR();       else
    if (table=="ChampSpells" && field=="L4")     res += sql_table_langEN_DE_FR();       else
    if (table=="ChampSpells" && field=="L5")     res += sql_table_langEN_DE_FR();       else
    if (table=="ChampSpells" && field=="L6")     res += sql_table_langEN_DE_FR();       else
    if (table=="ChampSpells" && field=="L7")     res += sql_table_langEN_DE_FR();       else
    if (table=="Ras_old" && field=="Name")       res += sql_table_langEN_DE();       else
    if (table=="Ras_old" && field=="Desc")       res += sql_table_langEN_DE();       else
    if (table=="RR_Names" && field=="Alb_Name")       res += sql_table_langEN_DE();       else
    if (table=="RR_Names" && field=="Mid_Name")       res += sql_table_langEN_DE();       else
    if (table=="RR_Names" && field=="Hib_Name")       res += sql_table_langEN_DE();       else
    {}

    return res;
}

//////////////////////////////////////////////////////////////////////////
CString CDBInterfaceSQL::sql_table_field(const CString& table, const CString& field)
{
    ASSERT(table.Left(1)>="A" && table.Left(1)<="Z");
    ASSERT(field.Left(1)>="A" && field.Left(1)<="Z");

    CString res = table + CString(".") + sql_table_field_no_tab(table,field);
    return res;
}


//////////////////////////////////////////////////////////////////////////
bool    CDBInterfaceSQL::sqlite3_column_bool(sqlite3_stmt* r,int n)
{
    return sqlite3_column_text(r, n)[0]=='T';
}


//////////////////////////////////////////////////////////////////////////
bool	CDBInterfaceSQL::DebugCheckIfSpecable(int class_id, const CString& str_line)
{
    sqlite3_stmt* res 
    = sql_prepare( "SELECT Classes.CLASS_ID "
                   "FROM Classes "
                   "LEFT JOIN Classes_Spelllines ON Classes.CLASS_ID = Classes_Spelllines.CLASS_ID "
                    "LEFT JOIN Spelllines ON Spelllines.SPELLLINE_ID = Classes_Spelllines.SPELLLINE_ID "
                   "LEFT JOIN Classes_Stylelines ON Classes.CLASS_ID = Classes_Stylelines.CLASS_ID "
                    "LEFT JOIN Stylelines ON Stylelines.STYLELINE_ID = Classes_Stylelines.STYLELINE_ID "
                   "WHERE ((Classes.CLASS_ID='%i') AND ((%s='%s') OR (%s='%s')));",
                    // where
                    class_id,
                    sql_table_field("Stylelines","Name"), str_line,
                    sql_table_field("Spelllines","SPEC_Name"), str_line
                );

    if (!res) return false;

    bool found = (sqlite3_step(res) == SQLITE_ROW);
    sqlite3_finalize(res); 

	return found;
}




/* -------------------------------------------------------------------------------
     GLOBAL LISTS
   -------------------------------------------------------------------------------*/
void	CDBInterfaceSQL::GetListOfRealms(CStringArray& output)
{
	output.RemoveAll();
	output.Add(GetRealmName(0));
	output.Add(GetRealmName(1));
	output.Add(GetRealmName(2));
}


//////////////////////////////////////////////////////////////////////////
CString	CDBInterfaceSQL::GetRealmName(int i)
{
    switch (i)
    {
        case R_ALBION:   return _T("Albion");
        case R_HIBERNIA: return _T("Hibernia");
        case R_MIDGARD:  return _T("Midgard");
    }
    return _T("");
}


//////////////////////////////////////////////////////////////////////////
int		CDBInterfaceSQL::GetRealmID(const CString &realm_name)
{
    if (realm_name.Left(3).CompareNoCase(_T("alb"))==0)	return R_ALBION;
    if (realm_name.Left(3).CompareNoCase(_T("hib"))==0) return R_HIBERNIA;
    if (realm_name.Left(3).CompareNoCase(_T("mid"))==0) return R_MIDGARD;
    return R_UNDEF;
}

//////////////////////////////////////////////////////////////////////////
int   CDBInterfaceSQL::GetRealm()
{
    return mn_selected_realm;
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::SelectRealm(int id)
{
    ASSERT(id>=-1 && id<=3); // Illegal ID
    mn_selected_realm = id;
}


void	CDBInterfaceSQL::GetListOfRaces(IntArray& output)
{
	ASSERT(mp_db); // Init not called
    ASSERT(m_class.id != -1);

	output.RemoveAll();

    sqlite3_stmt* res = sql_prepare( "SELECT RACE_ID FROM Classes_Races WHERE CLASS_ID='%i';", m_class.id);

    int rc;
    while ((rc=sqlite3_step(res)) == SQLITE_ROW)
    {
        output.Add(sqlite3_column_int(res, 0));
    }

    ASSERT(output.GetCount()>0);
    sqlite3_finalize(res); 
}

void        CDBInterfaceSQL::GetListOfClasses(IntArray& output)
{
    ASSERT(mp_db); // Init not called

    sqlite3_stmt* res;
    output.RemoveAll();

    if (mn_selected_realm != -1)
    {
        res = sql_prepare( "SELECT CLASS_ID FROM Classes WHERE Realm='%i';", mn_selected_realm);
    }
    else
    {
        res = sql_prepare( "SELECT CLASS_ID FROM Classes;");
    }
        

    while (sqlite3_step(res) == SQLITE_ROW)
    {
        output.Add(sqlite3_column_int(res, 0));
    }

    sqlite3_finalize(res); 
}


//////////////////////////////////////////////////////////////////////////
CString	CDBInterfaceSQL::GetClassName(int id)
{
    ASSERT(mp_db); // Init not called
    ASSERT(id!=-1); // No class selected

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT %s FROM Classes WHERE CLASS_ID='%i';",  
                sql_table_field_no_tab("Classes", "Name"),
                id);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    CString name = CString(sqlite3_column_text(res, 0));
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 

    return name;
}


//////////////////////////////////////////////////////////////////////////
mstring   CDBInterfaceSQL::GetClassName()
{
    ASSERT(m_class.id != -1); // No class selected
    return m_class.name;
}


//////////////////////////////////////////////////////////////////////////
bool	CDBInterfaceSQL::IsClassFemaleOnly()
{
	ASSERT(m_class.id != -1); // No class selected
    return m_class.IsFemaleOnly;
}


//////////////////////////////////////////////////////////////////////////
bool	CDBInterfaceSQL::IsClassListCaster()
{
    ASSERT(m_class.id != -1); // No class selected
    return m_class.IsListCaster;
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::GetClassesHPModifier(int &basehps, double& confactor)
{
    ASSERT(m_class.id != -1); // No class selected
    basehps = m_class.HP_base;
    confactor = m_class.HP_confactor;
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::GetClassesWFModifier(int &basewfs, double& conwf, int &basewfs_b, double& wffactor_b)
{
    ASSERT(m_class.id != -1); // No class selected

    basewfs    = m_class.WF_base;
    conwf      = m_class.WF_factor;
    basewfs_b  = m_class.WF_base_bow;
    wffactor_b = m_class.WF_factor_bow;

}

//////////////////////////////////////////////////////////////////////////
CString	CDBInterfaceSQL::GetRealmName()
{
    ASSERT(mp_db); // Init not called
	ASSERT(mn_selected_realm != -1); // No class selected
	
	return GetRealmName(mn_selected_realm);
}


int  CDBInterfaceSQL::GetRaceID()
{
	ASSERT(mp_db); // Init not called
    return mn_selected_race;
}


CString	CDBInterfaceSQL::GetRaceName()
{
	ASSERT(mn_selected_race != -1); // No class selected
    return GetRaceName(mn_selected_race);
}


CString  CDBInterfaceSQL::GetRaceName(int id)
{
    ASSERT(mp_db); // Init not called

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT %s FROM Race WHERE RACE_ID='%i';",  
        sql_table_field_no_tab("Race", "Name"),id);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    CString name = CString(sqlite3_column_text(res, 0));
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 

    return name;
}


void	CDBInterfaceSQL::GetRaceResis(CStringArray& names,IntArray& perc)
{  
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_race != -1); // No race selected

    // Get values
    sqlite3_stmt* res;
    res = sql_prepare( "SELECT Body,Cold,Crush,Energy,Heat,Matter,Slash,Spirit,Thrust FROM Race WHERE RACE_ID='%i';",  
        mn_selected_race);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);    
    int p[9];
    for (int t=0;t<9;++t)
        p[t] = sqlite3_column_int(res, t);
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 

    // Get Names
    res = sql_prepare( "SELECT %s FROM Spells_Resi ORDER BY ID;",  
        sql_table_field_no_tab("Spells_Resi","Name"));

    for (int t=0;t<9;++t)
    {
        VERIFY(sqlite3_step(res) == SQLITE_ROW);  
        if (p[t]>0)
        {
            perc.Add(p[t]);
            names.Add(CString(sqlite3_column_text(res, 0)));
        }
    }
    sqlite3_finalize(res); 
}


 bool    CDBInterfaceSQL::db_read_class(int class_id)
 {
    sqlite3_stmt* res;
    res = sql_prepare( "SELECT CLASS_ID, Realm, Name_%s, MORA_ID, IsListCaster, HP_Base, HP_Factor, WF_Base, WF_Factor, WF_Base_Bow, WF_Factor_Bow "
                       "FROM Classes WHERE CLASS_ID='%i';",  
                         langEN_DE_FR(),class_id);
    
    if (sqlite3_step(res) == SQLITE_ROW)
    {
        m_class.id = sqlite3_column_int(res, 0);
        m_class.realm = sqlite3_column_int(res, 1);
        m_class.name = UtfToStr(sqlite3_column_text(res,2));
        m_class.mora_ID = UtfToStr(sqlite3_column_text(res,3));
        m_class.IsListCaster = sqlite3_column_bool(res,4);

        m_class.HP_base = sqlite3_column_int(res,5);
        m_class.HP_confactor = sqlite3_column_double(res,6);
        m_class.WF_base = sqlite3_column_int(res,7);
        m_class.WF_factor = sqlite3_column_double(res,8);
        m_class.WF_base_bow = sqlite3_column_int(res,9);
        m_class.WF_factor_bow = sqlite3_column_double(res,10);


        ASSERT(sqlite3_step(res) == SQLITE_DONE);

        sqlite3_stmt* res2;
        res2 = sql_prepare( "SELECT Female_only FROM Classes_Races WHERE CLASS_ID='%i';", m_class.id);
        VERIFY(sqlite3_step(res2) == SQLITE_ROW);
        m_class.IsFemaleOnly = sqlite3_column_bool(res2, 0);
        sqlite3_finalize(res2); 

        ASSERT(m_class.realm >=0 && m_class.realm<=3); // illegal realm
    }
    else
    {
        m_class.id = -1;
        ASSERT(false); // no class found
    }


    sqlite3_finalize(res);
    return m_class.id != -1;
 }


void  CDBInterfaceSQL::SelectClass(int id)
{
    ASSERT(mp_db); // Init not called 

    if (id>0)
    {
       if ( id != m_class.id)   db_read_class(id);
       mn_selected_realm = m_class.realm;
    }
    else
    {
        m_class.id = -1;
        mn_selected_realm = -1;
        mn_selected_race = -1;
        mn_selected_styleline = -1;
        mn_selected_style = -1;
        mn_selected_spellline = -1;
        mn_selected_spell = -1;
        mn_selected_spellcat = -1;
        mn_selected_ra = -1;
        mn_selected_raNF = -1;
        mn_selected_mastertrack = -1;
    }
}



//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::SelectRace(int id)
{
    ASSERT(mp_db); // Init not called 

    mn_selected_race = id;


    // Check if selected class fits
    #ifdef DEBUG
       sqlite3_stmt* res = sql_prepare( "SELECT RACE_ID FROM Classes_Races WHERE RACE_ID='%i' AND CLASS_ID='%i';",  
            mn_selected_race,
            m_class.id);

       ASSERT(m_class.id == -1 || sqlite3_step(res) == SQLITE_ROW);
       sqlite3_finalize(res);
    #endif
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::SelectStyleLine(const CString& style)
{
    ASSERT(mp_db); // Init not called
    ASSERT(m_class.id != -1); // No class selected

    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT Stylelines.STYLELINE_ID "
        "FROM Stylelines INNER JOIN Classes_Stylelines ON Stylelines.STYLELINE_ID = Classes_Stylelines.STYLELINE_ID "
        "WHERE %s='%s' AND Classes_Stylelines.CLASS_ID='%i';",
        sql_table_field_no_tab("Stylelines", "Name"),
        sqlite3_escape_string(style),m_class.id);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    mn_selected_styleline = sqlite3_column_int(res, 0);
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::SelectStyle(const CString& style)
{
    ASSERT(mp_db); // Init not called
    ASSERT(mn_selected_styleline != -1); // No STYLELINE selected

    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT Stylelines_Styles.STYLE_ID " 
        "FROM Styles INNER JOIN Stylelines_Styles ON Styles.STYLE_ID = Stylelines_Styles.STYLE_ID "
        "WHERE Stylelines_Styles.STYLELINE_ID='%i' AND %s='%s';", 
        mn_selected_styleline, 
        sql_table_field("Styles", "Name"),sqlite3_escape_string(style));


    VERIFY(sqlite3_step(res) == SQLITE_ROW);  // STYLE NOT FOUND
    mn_selected_style = sqlite3_column_int(res, 0);
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 
}

//////////////////////////////////////////////////////////////////////////
void    CDBInterfaceSQL::SelectStyleID(int style_id)
{
    ASSERT(mp_db); // Init not called
    ASSERT(mn_selected_styleline != -1); // No STYLELINE selected
    ASSERT(style_id==-1 || style_id>0); 

    mn_selected_style = style_id;

    #ifdef _DEBUG
        if (style_id>0)
        {
            sqlite3_stmt* res;
            res = sql_prepare( 
                "SELECT STYLE_ID " 
                "FROM Stylelines_Styles "
                "WHERE STYLELINE_ID='%i' AND STYLE_ID='%i';", 
                mn_selected_styleline, style_id);

            VERIFY(sqlite3_step(res) == SQLITE_ROW);  // STYLE NOT FOUND
            ASSERT(sqlite3_step(res) == SQLITE_DONE);
            sqlite3_finalize(res); 
        }
    #endif
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::SelectSpellLine(const CString& spelllinename)
{
    ASSERT(mp_db); // Init not called
    ASSERT(m_class.id != -1); // No class selected

    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT Spelllines.SPELLLINE_ID "
        "FROM Spelllines INNER JOIN Classes_Spelllines ON Spelllines.SPELLLINE_ID = Classes_Spelllines.SPELLLINE_ID "
        "WHERE %s='%s' AND Classes_Spelllines.CLASS_ID='%i';",
        sql_table_field_no_tab("Spelllines", "Name_Base"),
        sqlite3_escape_string(spelllinename),m_class.id);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);    // SPELL-LINE NOT FOUND (may be it's not a BASE-Line?)
    mn_selected_spellline = sqlite3_column_int(res, 0);
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::SelectSpellCatBase(const CString& spellcat)
{
    ASSERT(mp_db); // Init not called
    ASSERT(mn_selected_spellline != -1); // No spellline selected

    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT Spelllines_Spellcat.SPELLCAT_ID "
        "FROM Spellcat INNER JOIN Spelllines_Spellcat ON Spellcat.SPELLCAT_ID = Spelllines_Spellcat.SPELLCAT_ID "
        "WHERE Spelllines_Spellcat.SPELLLINE_ID='%i' AND Spelllines_Spellcat.IsSpec='False' AND %s='%s';",
        mn_selected_spellline,
        sql_table_field_no_tab("Spellcat", "Name"),
        sqlite3_escape_string(spellcat));

    VERIFY(sqlite3_step(res) == SQLITE_ROW);    // SPELL-CAT NOT FOUND
    mn_selected_spellcat = sqlite3_column_int(res, 0);
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 
}
	
//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::SelectSpellCatSpec(const CString& spellcat)
{
    ASSERT(mp_db); // Init not called
    ASSERT(mn_selected_spellline != -1); // No spellline selected

    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT Spelllines_Spellcat.SPELLCAT_ID "
        "FROM Spellcat INNER JOIN Spelllines_Spellcat ON Spellcat.SPELLCAT_ID = Spelllines_Spellcat.SPELLCAT_ID "
        "WHERE Spelllines_Spellcat.SPELLLINE_ID='%i' AND Spelllines_Spellcat.IsSpec='True' AND %s='%s';",
        mn_selected_spellline,
        sql_table_field_no_tab("Spellcat", "Name"),
        sqlite3_escape_string(spellcat));

    VERIFY(sqlite3_step(res) == SQLITE_ROW);    // SPELL-CAT NOT FOUND
    mn_selected_spellcat = sqlite3_column_int(res, 0);
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::SelectSpell(const CString& spell, int level)
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_spellcat != -1); // No spelll-Cat selected

    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT Spells.SPELL_ID FROM Spells "
        "INNER JOIN Spellcats_Spells ON Spells.SPELL_ID = Spellcats_Spells.SPELL_ID "
        "WHERE Spellcats_Spells.SPELLCAT_ID='%i' AND %s='%s' AND Spells.Level='%i';",
        mn_selected_spellcat,
        sql_table_field_no_tab("Spells", "Name"),
        sqlite3_escape_string(spell),level);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);    // SPELL NOT FOUND
    mn_selected_spell = sqlite3_column_int(res, 0);
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 
}

//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::SelectSpellID(int spell_id)
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_spellcat != -1); // No spelll-Cat selected
    ASSERT(spell_id==-1 || spell_id>0); 

    mn_selected_spell = spell_id;

    #ifdef _DEBUG
        if (spell_id>0)
        {
            sqlite3_stmt* res;
            res = sql_prepare( 
                "SELECT SPELL_ID FROM Spellcats_Spells "
                "WHERE SPELLCAT_ID='%i' AND SPELL_ID='%i';",
                mn_selected_spellcat, spell_id);

            VERIFY(sqlite3_step(res) == SQLITE_ROW);  // SPELL NOT FOUND
            ASSERT(sqlite3_step(res) == SQLITE_DONE);
            sqlite3_finalize(res); 
        }
    #endif
}

//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::SelectRA(const CString& str_ra)
{
    ASSERT(mp_db); // Init not called
    ASSERT(m_class.id!=-1); // NO class selected (different classes may have differ points ... maybe obsolete)

    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT Ras_Old.ID FROM Ras_Old "
        "INNER JOIN Classes_RasOld ON Ras_Old.ID=Classes_RasOld.RAS_Old_ID "
        "WHERE %s='%s' AND Classes_RasOld.Class_ID='%i';", 
        sql_table_field("Ras_old","Name"),
        sqlite3_escape_string(str_ra),m_class.id);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);// RA NOT FOUND
    mn_selected_ra = sqlite3_column_int(res, 0);
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 
}


//////////////////////////////////////////////////////////////////////////
int     CDBInterfaceSQL::GetClassID(const CString& classname)
{
    ASSERT(mp_db); // Init not called 

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT CLASS_ID FROM Classes WHERE %s='%s';",  
        sql_table_field_no_tab("Classes", "Name"),sqlite3_escape_string(classname));

    int classid = -1;
    if (sqlite3_step(res) == SQLITE_ROW)
    {
        classid = sqlite3_column_int(res, 0);
        ASSERT(sqlite3_step(res) == SQLITE_DONE);
    }
    sqlite3_finalize(res);

    return classid;
}


//////////////////////////////////////////////////////////////////////////
int    CDBInterfaceSQL::GetClassID()
{
    return m_class.id;
}



/* -------------------------------------------------------------------------------
     STATS / SKILLPOINTS FUNCTION
   -------------------------------------------------------------------------------*/
void	CDBInterfaceSQL::GetStats(int stats[8])
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_race != -1); // No race selected

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT STR,CON,DEX,QUI,_INT,PIE,EMP,CHA FROM Race WHERE RACE_ID='%i';",  
        mn_selected_race);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);    // SPELL NOT FOUND
    stats[0] = sqlite3_column_int(res, 0);
    stats[1] = sqlite3_column_int(res, 1);
    stats[2] = sqlite3_column_int(res, 2);
    stats[3] = sqlite3_column_int(res, 3);
    stats[4] = sqlite3_column_int(res, 4);
    stats[5] = sqlite3_column_int(res, 5);
    stats[6] = sqlite3_column_int(res, 6);
    stats[7] = sqlite3_column_int(res, 7);
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::GetStatsLevel(int stats[8], float level)
{
    ASSERT(mn_selected_race != -1); // No race selected
    ASSERT(m_class.id != -1); // No class selected

    GetStats(stats);

    int lround = (int)level;

    if (level>5)
    {

        sqlite3_stmt* res;
        res = sql_prepare( "SELECT Primary_Stat,Secondy_Stat,Tertiary_Stat FROM Classes WHERE CLASS_ID='%i';",  
            m_class.id);

        VERIFY(sqlite3_step(res) == SQLITE_ROW);    // SPELL NOT FOUND

        int p1 = sqlite3_column_int(res, 0);
        int p2 = sqlite3_column_int(res, 1);
        int p3 = sqlite3_column_int(res, 2);
        ASSERT(p1>=0&&p1<8 && p2>=0&&p2<8 && p3>=0&&p3<8);


        stats[p1] += lround-5;
        stats[p2] += (lround-4)/2;
        stats[p3] += (lround/3)-1;
        ASSERT(sqlite3_step(res) == SQLITE_DONE);
        sqlite3_finalize(res); 
    }
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::GetStatsPrimary(int pri[4])
{
    ASSERT(mp_db); // Init not called 
	ASSERT(m_class.id != -1); // No class selected


    sqlite3_stmt* res;
    res = sql_prepare( "SELECT Primary_Stat,Secondy_Stat,Tertiary_Stat,Cast_Stat FROM Classes WHERE CLASS_ID='%i';",  
            m_class.id);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);    // SPELL NOT FOUND
    pri[0] = sqlite3_column_int(res, 0);
    pri[1] = sqlite3_column_int(res, 1);
    pri[2] = sqlite3_column_int(res, 2);
    pri[3] = sqlite3_column_int(res, 3);
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 

    if (pri[3]>7)   pri[3]=-1;
}


//////////////////////////////////////////////////////////////////////////
int		CDBInterfaceSQL::GetSkillPoints(float level)
{
    ASSERT(mp_db); // Init not called
    ASSERT(m_class.id != -1); // No class selected


    sqlite3_stmt* res;
    res = sql_prepare( "SELECT Skillfactor FROM Classes WHERE CLASS_ID='%i';", m_class.id);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    double factor = sqlite3_column_double(res, 0);
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 


	int skillpkt = 0;

	for (int n=2;n<=level && n<=5;n++)
		skillpkt += (int)(n);

	for (float n=6;n<=level && n<=80;n++)
		skillpkt += (int)(n*factor+0.00001);	// prevent float error: 1.8f*10 = 17.99999 

	for (int n=40;n<=level-0.5f && n<80;n++)
		skillpkt += (int)(n*factor/2.0+0.00001);

	return skillpkt;
}



/* -------------------------------------------------------------------------------
     STYLES FUNCTION
   -------------------------------------------------------------------------------*/
void	CDBInterfaceSQL::GetListOfStyleLines(CStringArray& output)
{
    ASSERT(mp_db); // Init not called 
    ASSERT(m_class.id != -1); // No class selected

    output.RemoveAll();

    sqlite3_stmt* res = sql_prepare( 
            "SELECT %s "
            "FROM Stylelines "
            "INNER JOIN Classes_Stylelines ON Stylelines.STYLELINE_ID = Classes_Stylelines.STYLELINE_ID "
            "WHERE Classes_Stylelines.CLASS_ID='%i';",
            sql_table_field("Stylelines","Name"),m_class.id);
        
       
    int rc;
    while ((rc=sqlite3_step(res)) == SQLITE_ROW)
    {
        output.Add(CString(sqlite3_column_text(res, 0)));
    }

    sqlite3_finalize(res); 
}


//////////////////////////////////////////////////////////////////////////
int		CDBInterfaceSQL::GetStyleLineID()
{
	return mn_selected_styleline;
}


//////////////////////////////////////////////////////////////////////////
int		CDBInterfaceSQL::GetStyleID()
{
	return mn_selected_style;
}

//////////////////////////////////////////////////////////////////////////
int     CDBInterfaceSQL::FindStyleLine(const char* name)
{
    ASSERT(mp_db); // Init not called

    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT Stylelines.STYLELINE_ID FROM Stylelines WHERE %s='%s';",
        sql_table_field_no_tab("Stylelines", "Name"),
        sqlite3_escape_string(name));

    if (sqlite3_step(res) != SQLITE_ROW) 
    {
        sqlite3_finalize(res); 
        return -1;
    }
    int id = sqlite3_column_int(res, 0);
    // ASSERT(sqlite3_step(res) == SQLITE_DONE);  NOTE: style lines are not unique
    sqlite3_finalize(res); 

    return id;
}


void    CDBInterfaceSQL::GetListOfStyles(CStringArray* names, IntArray* level, IntArray* ids)
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_styleline != -1); // No STYLE selected

    if (names) names->RemoveAll();
    if (level) level->RemoveAll();
    if (ids)   ids->RemoveAll();

    sqlite3_stmt* res = sql_prepare( 

        "SELECT %s, Styles.Level, Styles.STYLE_ID "
        "FROM Styles "
        "INNER JOIN Stylelines_Styles ON Styles.STYLE_ID = Stylelines_Styles.STYLE_ID "
        "WHERE Stylelines_Styles.STYLELINE_ID='%i' "
        "ORDER BY Styles.Level;",
        sql_table_field("Styles","Name"), 
        mn_selected_styleline);


    int rc;
    while ((rc=sqlite3_step(res)) == SQLITE_ROW)
    {
        if (names) names->Add(CString(sqlite3_column_text(res, 0)));
        if (level) level->Add(sqlite3_column_int(res,1));
        if (ids)   ids->Add(sqlite3_column_int(res,2));
    }

    sqlite3_finalize(res); 
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::GetStyleDescription(CStringArray& name, CStringArray& val, int style /*=-1*/)
{
    ASSERT(mp_db); // Init not called 
    ASSERT(style!=-1 || mn_selected_style!= -1); // No STYLE selected

    name.RemoveAll();
    val.RemoveAll();

    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT %s, Styles.Level, Styles.Open_POS, pre_style.%s, %s, Styles.Open_RES, %s, Styles.Open_Stealthed " // 0-7
         ", attack_bonus.%s, %s, %s, damage.%s, %s, Styles.Growth_Rate "
        "FROM Styles "
        "LEFT JOIN Styles AS pre_style ON Styles.Open_Style = pre_style.STYLE_ID "
        "INNER JOIN Styles_Open_Pos ON Styles_Open_Pos.Opening_POS_ID = Styles.Open_POS "
        "INNER JOIN Styles_Open_Result ON Styles_Open_Result.ID = Styles.Open_RES "
        "LEFT JOIN Styles_Bonus AS attack_bonus ON Styles.Attack_Bonus = attack_bonus.BONUS_ID "
        "LEFT JOIN Styles_Bonus AS damage ON Styles.Damage = damage.BONUS_ID "
        "LEFT JOIN Styles_Defense_Bonu ON Styles.Defense = Styles_Defense_Bonu.BONUS_ID "
        "WHERE Styles.STYLE_ID='%i';",

        sql_table_field("Styles","Name"),               // 0
        sql_table_field_no_tab("Styles","Name"),        // 3
        sql_table_field("Styles_Open_Pos","Name"),      // 4
        sql_table_field("Styles_Open_Result","Name"),   // 6
        sql_table_field_no_tab("Styles_Bonus","Name"),  // 8
        sql_table_field("Styles_Defense_Bonu","Name"),  // 9
        sql_table_field("Styles","Fatigue_Cost"),       // 10
        sql_table_field_no_tab("Styles_Bonus","Name"),  // 11
        sql_table_field("Styles","Effect"),             // 12
        style==-1?mn_selected_style:style);


    VERIFY(sqlite3_step(res) == SQLITE_ROW);

        name.Add(_T("Name"));		val.Add(CString(sqlite3_column_text(res,0)));
        name.Add(_T("Level"));		val.Add(CString(sqlite3_column_text(res,1)));

        // is "Ability"?
        if (sqlite3_column_int(res,2)!=1)
        {
            // Prerequisite
            CString temp;
            if (sqlite3_column_value(res,3)!= NULL) temp += CString(sqlite3_column_text(res,3));
            if (sqlite3_column_int(res,2)>2)        temp += CString(sqlite3_column_text(res,4));
            if (sqlite3_column_int(res,5)>1)        temp += CString(sqlite3_column_text(res,6));
            if (sqlite3_column_int(res,7))  
            {   
                if (!temp.IsEmpty()) temp+=",";
                temp += "Stealthed";
            }
            
            name.Add(_T("Prerequisite"));
            val.Add(temp);

            // Attack
            name.Add(_T("To-Hit"));
            val.Add(CString(sqlite3_column_text(res,8)));

            // Defense
            name.Add(_T("Defense"));
            val.Add(CString(sqlite3_column_text(res,9)));

            // fatigue
            name.Add(_T("Fatigue Cost"));
            val.Add(CString(sqlite3_column_text(res,10)));

            // Damage
            name.Add(_T("Damage"));
            val.Add(CString(sqlite3_column_text(res,11)));

            // Effect
            name.Add(_T("Effect"));
            val.Add(CString(sqlite3_column_text(res,12)));

            // Growthrate
            double f_growth = sqlite3_column_double(res,13);

            name.Add(_T("Growth rate"));
            if (f_growth<0)	    val.Add(_T("Special"));   else
            if (f_growth>10)    val.Add(_T("-?-"));       else
            {
                CString temp;
                temp.Format(_T("%g"),f_growth);
                val.Add(temp);
            }
        }

    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 
}


//////////////////////////////////////////////////////////////////////////
int		CDBInterfaceSQL::GetStylePrePos()
{
    ASSERT(mp_db); // Init not called 
	ASSERT(mn_selected_style != -1); // No STYLE selected


    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT Open_Stealthed, Open_Style, Open_POS, Open_RES "
        "FROM Styles WHERE Styles.STYLE_ID='%i';",
        mn_selected_style);


    
    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    
        int preop = (sqlite3_column_int(res,0)>0?128:0);

        int pre_style= sqlite3_column_int(res,1);
        int pre_pos  = sqlite3_column_int(res,2);
        int pre_res  = sqlite3_column_int(res,3);

        // Pre-Style
        if (pre_style !=0 )
        {
            preop |= 8;
        }
        else
        // Pre-Position
        if (pre_pos!= 2) // not "any"
        {
            if (pre_pos== 4) preop |= 1; // Front
            if (pre_pos== 3) preop |= 2; // behind
            if (pre_pos== 5) preop |= 3; // side
            if (pre_pos== 1) preop |= 9; // ability
        }
        else
        // Pre-Result
        if (pre_res!= 1) // not "None"
        {
            if (pre_res== 4) preop |= 4; // evade
            if (pre_res== 2) preop |= 5; // block
            if (pre_res== 3) preop |= 6; // parry
            if (pre_res==5 || pre_res==6 || pre_res==7) preop |= 7; // Target
        }

    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 

    return preop;
}



//////////////////////////////////////////////////////////////////////////
CString	CDBInterfaceSQL::GetStylePreStyle()
{
    ASSERT(mp_db); // Init not called
	ASSERT(mn_selected_style != -1); // No STYLE selected

    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT pre_style.%s FROM Styles "
        "INNER JOIN Styles AS pre_style ON Styles.Open_Style = pre_style.STYLE_ID "
        "WHERE Styles.STYLE_ID='%i';",
        sql_table_field_no_tab("Styles", "Name"),
        mn_selected_style);

    CString style;
    if (sqlite3_step(res) == SQLITE_ROW) 
    {
        style = CString(sqlite3_column_text(res, 0));
        ASSERT(sqlite3_step(res) == SQLITE_DONE);
    }
    sqlite3_finalize(res); 

    return style;
}


//////////////////////////////////////////////////////////////////////////
int	CDBInterfaceSQL::GetStylePreStyleID()
{
    ASSERT(mp_db); // Init not called
    ASSERT(mn_selected_style != -1); // No STYLE selected

    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT Open_Style FROM Styles WHERE STYLE_ID='%i';",
        mn_selected_style);

    int id = -1;
    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    if (sqlite3_column_text(res, 0)!=NULL)
        id = sqlite3_column_int(res, 0);

    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 

    return id;
}


CString	CDBInterfaceSQL::GetStyleLineName()
{
 	ASSERT(mn_selected_styleline != -1); // No STYLELINE selected
    return GetStyleLineNameEx(mn_selected_styleline);
}

CString CDBInterfaceSQL::GetStyleLineNameEx(int ext)
{
    ASSERT(mp_db); // Init not called

    sqlite3_stmt* res = sql_prepare( 
        "SELECT %s FROM Stylelines WHERE STYLELINE_ID='%i';",
        sql_table_field_no_tab("Stylelines","Name"),ext);


    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    CString name = CString(sqlite3_column_text(res, 0));
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 

    return name;
}


CString CDBInterfaceSQL::GetStyleDetailtext(int id)
{
    CStringArray properties_names;
    CStringArray properties_vals;

    GetStyleDescription(properties_names,properties_vals,id);


    ASSERT(properties_names[0]=="Name");

    CString text = _T("<al_c><b>"); 
    text += properties_vals[0];
    text += _T("</b><br><hr=100%><al><br>");

    

    CString desc = GetAbilityDesc(properties_vals[0],true);

    if (!desc.IsEmpty())
    {
        text += desc;
        text += "<br><hr=100%><al><br>";
    }



    for (int t4=1;t4<properties_names.GetCount();t4++)
    {
        TCHAR* tabs[] =
        {
            _T(":<t>"),
            _T(":<t=2>"),	// level
            _T(":<t>"),		// pre
            _T(":<t=2>"),	// attack
            _T(":<t=2>"),	// defense
            _T(":<t=1>"),	// Fat
            _T(":<t=2>"),	// damage
            _T(":<t=2>"),	// effect
            _T(":<t=1>")	// growth
        };


        if (t4 == 5) // fat
        {
            CString temp;
            if (properties_vals[t4]=="low")     temp = " (<< 5%)"; else
            if (properties_vals[t4]=="med")     temp = " (5%-10%)"; else
            if (properties_vals[t4]=="high")    temp = " (>=10%)";  else
            if (properties_vals[t4]=="Niedrig") temp = " (<< 5%)"; else
            if (properties_vals[t4]=="Normal")  temp = " (5%-10%)"; else
            if (properties_vals[t4]=="Hoch")    temp = " (>=10%)"; 

            text += properties_names[t4] + tabs[t4] + properties_vals[t4] + temp + _T("<br>");
        }
        else
        {
            text += properties_names[t4] + tabs[t4] + properties_vals[t4] + _T("<br>");
        }

    }

    return text;
}


//////////////////////////////////////////////////////////////////////////
CString	CDBInterfaceSQL::GetStyleDescriptionText()
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_style != -1); // No STYLELINE selected

    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT %s FROM Ability_Desc "
        "INNER JOIN Styles ON Styles.Name_EN = Ability_Desc.Name_EN "
        "WHERE Styles.STYLE_ID='%i' AND Ability_Desc.Type='6';", // Style
        sql_table_field("Ability_Desc","Desc"),mn_selected_style);


    CString eff;
    if (sqlite3_step(res) == SQLITE_ROW)
    {
        eff = CString(sqlite3_column_text(res,0));
        ASSERT(sqlite3_step(res) == SQLITE_DONE);
    }
    sqlite3_finalize(res); 

    return eff;
}


//////////////////////////////////////////////////////////////////////////
bool	CDBInterfaceSQL::IsStyleLineAutotrain()
{
    ASSERT(mp_db); // Init not called 
    ASSERT(m_class.id != -1); // No CLASS selected
    ASSERT(mn_selected_styleline != -1); // No STYLELine selected

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT Autotrain FROM Classes_Stylelines WHERE "
                       "CLASS_ID='%i' AND STYLELINE_ID='%i';", 
                       m_class.id,mn_selected_styleline);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    bool isauto = sqlite3_column_bool(res, 0);
    sqlite3_finalize(res); 

    return isauto;
}





/* -------------------------------------------------------------------------------
     SPELL FUNCTION
   -------------------------------------------------------------------------------*/
void	CDBInterfaceSQL::GetListOfAllSpellLines(CStringArray& output)
{
    ASSERT(mp_db); // Init not called 
    ASSERT(m_class.id != -1); // No class selected

    output.RemoveAll();

    sqlite3_stmt* res = sql_prepare( 
        "SELECT %s,%s FROM Spelllines "
        "INNER JOIN Classes_Spelllines ON Spelllines.SPELLLINE_ID = Classes_Spelllines.SPELLLINE_ID "
        "WHERE Classes_Spelllines.CLASS_ID='%i';",
        sql_table_field("Spelllines","Name_Base"),
        sql_table_field("Spelllines","Name_Spec"),
        m_class.id);

    int rc;
    while ((rc=sqlite3_step(res)) == SQLITE_ROW)
    {
        output.Add(CString(sqlite3_column_text(res, 0)));
        output.Add(CString(sqlite3_column_text(res, 1)));
    }

    sqlite3_finalize(res); 
}




//////////////////////////////////////////////////////////////////////////
bool   CDBInterfaceSQL::IsFakeSpell(int id)
{
    ASSERT(mp_db); // Init not called 

    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT SPELLLINE_ID FROM Spelllines WHERE SPELLLINE_ID='%i' AND IsFake='true';", id);

    bool isfake = (sqlite3_step(res) == SQLITE_ROW);
    sqlite3_finalize(res); 

    return isfake;
}



//////////////////////////////////////////////////////////////////////////
CString    CDBInterfaceSQL::GetSpellLineNameEx(int ext)
{
    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT %s FROM Spelllines WHERE SPELLLINE_ID='%i';",
        sql_table_field_no_tab("Spelllines", "Name_Base"),
        ext);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);  
    CString name = CString(sqlite3_column_text(res, 0));
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 

    return name;
}

//////////////////////////////////////////////////////////////////////////
int	CDBInterfaceSQL::FindSpellLine(const CString& name)
{
    ASSERT(mp_db); // Init not called 
    ASSERT(m_class.id != -1); // No CLASS selected


    sqlite3_stmt* res = sql_prepare( 
        "SELECT Spelllines.SPELLLINE_ID FROM Spelllines "
        "INNER JOIN Classes_Spelllines ON Spelllines.SPELLLINE_ID = Classes_Spelllines.SPELLLINE_ID "
        "WHERE %s='%s'AND Classes_Spelllines.Class_ID=%i;",
        sql_table_field("Spelllines","Name_Base"),
        sqlite3_escape_string(name),
		m_class.id);

    if (sqlite3_step(res) != SQLITE_ROW)
    {
        sqlite3_finalize(res); 
        return -1;
    }

    int idx = sqlite3_column_int(res, 0);
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 

    return idx;
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::GetListOfSpellLines(CStringArray& output)
{
    ASSERT(mp_db); // Init not called 
    ASSERT(m_class.id != -1); // No class selected

    output.RemoveAll();

    sqlite3_stmt* res = sql_prepare( 
        "SELECT %s FROM Spelllines "
        "INNER JOIN Classes_Spelllines ON Spelllines.SPELLLINE_ID = Classes_Spelllines.SPELLLINE_ID "
        "WHERE Classes_Spelllines.CLASS_ID='%i';",
        sql_table_field("Spelllines","Name_Base"),
        m_class.id);

    int rc;
    while ((rc=sqlite3_step(res)) == SQLITE_ROW)
    {
        output.Add(CString(sqlite3_column_text(res, 0)));
    }

    sqlite3_finalize(res); 
}


//////////////////////////////////////////////////////////////////////////
CString	CDBInterfaceSQL::GetSkillName()
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_spellline != -1); // No SpellLine selected

    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT %s FROM Spelllines WHERE SPELLLINE_ID='%i';",
        sql_table_field_no_tab("Spelllines", "SPEC_Name"),
        mn_selected_spellline);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);  
    CString name = CString(sqlite3_column_text(res, 0));
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 

    return name;
}


//////////////////////////////////////////////////////////////////////////
CString	CDBInterfaceSQL::GetSpellLineNameBase()
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_spellline != -1); // No SpellLine selected

    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT %s FROM Spelllines WHERE SPELLLINE_ID='%i';",
        sql_table_field_no_tab("Spelllines", "Name_Base"),
        mn_selected_spellline);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);  
    CString name = CString(sqlite3_column_text(res, 0));
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 

    return name;
}


//////////////////////////////////////////////////////////////////////////
CString	CDBInterfaceSQL::GetSpellLineNameSpec()
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_spellline != -1); // No SpellLine selected

    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT %s FROM Spelllines WHERE SPELLLINE_ID='%i';",
        sql_table_field_no_tab("Spelllines", "Name_Spec"),
        mn_selected_spellline);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);  
    CString name = CString(sqlite3_column_text(res, 0));
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 

    return name;
}


//////////////////////////////////////////////////////////////////////////
bool	CDBInterfaceSQL::HasBaseSpells()
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_spellline != -1); // No SpellLine selected

    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT IsSpec FROM Spelllines_Spellcat "
        "WHERE SPELLLINE_ID='%i' AND IsSpec='False'; ",
        mn_selected_spellline);

    bool has_spells = (sqlite3_step(res) == SQLITE_ROW);
    sqlite3_finalize(res); 

    return has_spells;
}


//////////////////////////////////////////////////////////////////////////
bool	CDBInterfaceSQL::HasSpecSpells()
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_spellline != -1); // No SpellLine selected

    sqlite3_stmt* res;
    res = sql_prepare( 
            "SELECT IsSpec FROM Spelllines_Spellcat "
            "WHERE SPELLLINE_ID='%i' AND IsSpec='True'; ",
            mn_selected_spellline);

    bool has_spells = (sqlite3_step(res) == SQLITE_ROW);
    sqlite3_finalize(res); 

    return has_spells;
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::GetListOfSpellCatsBase(CStringArray& names)
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_spellline != -1); // No SpellLine selected

    names.RemoveAll();

    sqlite3_stmt* res = sql_prepare( 
        "SELECT %s "
        "FROM Spellcat INNER JOIN Spelllines_Spellcat ON Spellcat.SPELLCAT_ID = Spelllines_Spellcat.SPELLCAT_ID "
        "WHERE Spelllines_Spellcat.SPELLLINE_ID='%i' AND Spelllines_Spellcat.IsSpec='False';",
        sql_table_field("Spellcat","Name"),
        mn_selected_spellline);

    int rc;
    while ((rc=sqlite3_step(res)) == SQLITE_ROW)
    {
        names.Add(CString(sqlite3_column_text(res, 0)));
    }

    sqlite3_finalize(res); 
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::GetListOfSpellCatsSpec(CStringArray& names)
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_spellline != -1); // No SpellLine selected

    names.RemoveAll();

    sqlite3_stmt* res = sql_prepare( 
        "SELECT %s "
        "FROM Spellcat INNER JOIN Spelllines_Spellcat ON Spellcat.SPELLCAT_ID = Spelllines_Spellcat.SPELLCAT_ID "
        "WHERE Spelllines_Spellcat.SPELLLINE_ID='%i' AND Spelllines_Spellcat.IsSpec='True';",
        sql_table_field("Spellcat","Name"),
        mn_selected_spellline);

    int rc;
    while ((rc=sqlite3_step(res)) == SQLITE_ROW)
    {
        names.Add(CString(sqlite3_column_text(res, 0)));
    }

    sqlite3_finalize(res); 
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::GetListOfSpellCatsBaseAndID(CStringArray& names, IntArray& ids)
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_spellline != -1); // No SpellLine selected

    names.RemoveAll();
    ids.RemoveAll();

    sqlite3_stmt* res = sql_prepare( 
        "SELECT %s, Spellcat.Ident_ID "
        "FROM Spellcat INNER JOIN Spelllines_Spellcat ON Spellcat.SPELLCAT_ID = Spelllines_Spellcat.SPELLCAT_ID "
        "WHERE Spelllines_Spellcat.SPELLLINE_ID='%i' AND Spelllines_Spellcat.IsSpec='False';",
        sql_table_field("Spellcat","Name"),
        mn_selected_spellline);

    int rc;
    while ((rc=sqlite3_step(res)) == SQLITE_ROW)
    {
        names.Add(CString(sqlite3_column_text(res, 0)));
        ids.Add(sqlite3_column_int(res, 1));
    }

    sqlite3_finalize(res); 
}

//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::GetListOfSpellCatsSpecAndID(CStringArray& names, IntArray& ids)
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_spellline != -1); // No SpellLine selected

    names.RemoveAll();
    ids.RemoveAll();

    sqlite3_stmt* res = sql_prepare( 
        "SELECT %s, Spellcat.Ident_ID "
        "FROM Spellcat INNER JOIN Spelllines_Spellcat ON Spellcat.SPELLCAT_ID = Spelllines_Spellcat.SPELLCAT_ID "
        "WHERE Spelllines_Spellcat.SPELLLINE_ID='%i' AND Spelllines_Spellcat.IsSpec='True';",
        sql_table_field("Spellcat","Name"),
        mn_selected_spellline);

    int rc;
    while ((rc=sqlite3_step(res)) == SQLITE_ROW)
    {
        names.Add(CString(sqlite3_column_text(res, 0)));
        ids.Add(sqlite3_column_int(res, 1));
    }

    sqlite3_finalize(res); 
}



//////////////////////////////////////////////////////////////////////////
int		CDBInterfaceSQL::GetSpellCatDisplayFlag()
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_spellcat != -1); // No SpellCat selected

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT Display_Flag FROM Spellcat WHERE Spellcat_ID='%i';",
        mn_selected_spellcat);

    int disp;
    if (sqlite3_step(res) == SQLITE_ROW)
        disp = sqlite3_column_int(res,0);
    sqlite3_finalize(res); 

    return disp;
}



//////////////////////////////////////////////////////////////////////////
void    CDBInterfaceSQL::GetListOfSpells(CStringArray* names, IntArray* levels, IntArray* ids)
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_spellcat != -1); // No SpellCat selected

    if (names) names->RemoveAll();
    if (levels) levels->RemoveAll();
    if (ids) ids->RemoveAll();

    sqlite3_stmt* res = sql_prepare( 
            "SELECT %s, Spells.Level, Spells.SPELL_ID FROM Spells "
            "INNER JOIN Spellcats_Spells ON Spells.SPELL_ID = Spellcats_Spells.SPELL_ID "
            "WHERE Spellcats_Spells.SPELLCAT_ID='%i' "
            "ORDER BY Spells.Level;",
            sql_table_field("Spells","Name"), 
            mn_selected_spellcat);

    int rc;
    while ((rc=sqlite3_step(res)) == SQLITE_ROW)
    {
        if (names)  names->Add(CString(sqlite3_column_text(res, 0)));
        if (levels) levels->Add(sqlite3_column_int(res,1));
        if (ids)    ids->Add(sqlite3_column_int(res,2));
    }

    ASSERT(!names || names->GetCount()>0);

    sqlite3_finalize(res); 
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::GetSpellDescription(CStringArray& name, CStringArray& val)
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_spell != -1); // No Spell selected

    name.RemoveAll();
    val.RemoveAll();


    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT %s, Spells.Level, %s, Spells.Times, Spells.Range, Spells.Costs, %s FROM Spells "
        "INNER JOIN Targets ON Spells.Target=Targets.TARGET_ID "
        "WHERE SPELL_ID='%i';",
        sql_table_field("Spells","Name"),
        sql_table_field("Targets","Name"),
        sql_table_field("Spells","Effect"),
        mn_selected_spell);

    CString eff;
    VERIFY(sqlite3_step(res) == SQLITE_ROW);
        name.Add(_T("name"));		val.Add(CString(sqlite3_column_text(res,0)));
        name.Add(_T("level"));		val.Add(CString(sqlite3_column_text(res,1)));
        name.Add(_T("Target"));		val.Add(CString(sqlite3_column_text(res,2)));
        name.Add(_T("Times"));		val.Add(CString(sqlite3_column_text(res,3)));
        name.Add(_T("Range"));		val.Add(CString(sqlite3_column_text(res,4)));
        name.Add(_T("Costs"));		val.Add(CString(sqlite3_column_text(res,5)));
        name.Add(_T("Effect"));		val.Add(CString(sqlite3_column_text(res,6)));
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 
}


//////////////////////////////////////////////////////////////////////////
CString	CDBInterfaceSQL::GetSpellDescriptionEffect()
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_spell != -1); // No Spell selected

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT %s FROM Spells WHERE Spell_ID='%i';",
                        sql_table_field("Spells","Effect"),
                        mn_selected_spell);

    CString eff;
    if (sqlite3_step(res) == SQLITE_ROW)
        eff = CString(sqlite3_column_text(res,0));
    sqlite3_finalize(res); 

    return eff;
}


//////////////////////////////////////////////////////////////////////////
CString CDBInterfaceSQL::GetSpellDamType()
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_spell != -1); // No Spell selected

    sqlite3_stmt* res;
    res = sql_prepare( 
            "SELECT %s FROM Spells "
            "INNER JOIN Spells_Resi ON Spells_Resi.ID = Spells.Resi "
            "WHERE Spell_ID='%i';",
        sql_table_field("Spells_Resi","Name"),
        mn_selected_spell);

    CString eff;
    if (sqlite3_step(res) == SQLITE_ROW)
        eff = CString(sqlite3_column_text(res,0));
    sqlite3_finalize(res); 

    return eff;

}


//////////////////////////////////////////////////////////////////////////
CString	CDBInterfaceSQL::GetHighestSpellEffect(int level)
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_spellcat != -1); // No SpellCat selected

    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT %s FROM Spells "
        "INNER JOIN Spellcats_Spells ON Spells.SPELL_ID = Spellcats_Spells.SPELL_ID "
        "WHERE Spellcats_Spells.SPELLCAT_ID='%i' AND Spells.Level<='%i' "
        "ORDER BY Spells.Level DESC;",
        sql_table_field("Spells","Effect"),
        mn_selected_spellcat,level);

    CString eff;
    if (sqlite3_step(res) == SQLITE_ROW)
        eff = CString(sqlite3_column_text(res,0));
    sqlite3_finalize(res); 

    return eff;
}




CString	CDBInterfaceSQL::GetSpellDescriptionText()
{
    ASSERT(mp_db); // Init not called 
	ASSERT(mn_selected_spellcat != -1); // No SpellCat selected
	if (mn_selected_spellcat==-1) return _T("");


    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT %s FROM Spellcat_descriptio "
        "INNER JOIN Spellcat ON Spellcat_descriptio.SPELLCAT_DESC_ID = Spellcat.SPELLCAT_DESC_ID "
        "WHERE Spellcat.SPELLCAT_ID='%i';",
        sql_table_field("Spellcat_descriptio","Text"),
        mn_selected_spellcat);

    CString eff;
    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    eff = CString(sqlite3_column_text(res,0));
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 

    return eff;
}


bool	CDBInterfaceSQL::IsSpellLineAutotrain()
{
    ASSERT(mp_db); // Init not called 
    ASSERT(m_class.id != -1); // No CLASS selected
    ASSERT(mn_selected_spellline != -1); // No STYLELine selected

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT Autotrain FROM Classes_Spelllines WHERE "
        "CLASS_ID='%i' AND SPELLLINE_ID='%i';", 
        m_class.id,mn_selected_spellline);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    bool isauto = sqlite3_column_bool(res, 0);
    sqlite3_finalize(res); 

    return isauto;
}



// ----------------------------------------------------
// RAs
// ----------------------------------------------------
void	CDBInterfaceSQL::GetListOfRAs(CStringArray& output, IntArray&type)
{
    ASSERT(mp_db); // Init not called 
    ASSERT(m_class.id != -1); // no selected class 

    output.RemoveAll();

    sqlite3_stmt* res = sql_prepare( 
        "SELECT %s, type FROM Ras_old "
        "INNER JOIN Classes_RasOld ON Ras_old.ID = Classes_RasOld.RAs_Old_ID "
        "WHERE Classes_RasOld.CLASS_ID='%i';",
        sql_table_field("Ras_old","Name"),  m_class.id);

    int rc;
    while ((rc=sqlite3_step(res)) == SQLITE_ROW)
    {
        output.Add(CString(sqlite3_column_text(res, 0)));
        type.Add(2-sqlite3_column_int(res, 1));
    }

    sqlite3_finalize(res); 
}


int		CDBInterfaceSQL::GetRAReUseTime()
{
    ASSERT(mp_db); // Init not called 
	ASSERT(mn_selected_ra != -1); // No RA selected

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT reuse_time FROM Ras_old WHERE id='%i';",mn_selected_ra);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    int timer = sqlite3_column_int(res,0);
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 

    return timer;
}


void	CDBInterfaceSQL::GetRALevels(int l[5])
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_ra != -1); // No RA selected

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT l1,l2,l3,l4,l5 FROM Ras_old WHERE id='%i';",mn_selected_ra);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    l[0] = sqlite3_column_int(res,0);
    l[1] = sqlite3_column_int(res,1);
    l[2] = sqlite3_column_int(res,2);
    l[3] = sqlite3_column_int(res,3);
    l[4] = sqlite3_column_int(res,4);
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 
}

	

void	CDBInterfaceSQL::GetRARequirement(CString& name, int& level)
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_ra != -1); // No RA selected

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT Ra_Req.%s, Ras_old.reqlevel FROM Ras_old "
            "LEFT JOIN Ras_old AS Ra_Req ON Ra_Req.id = Ras_old.requier "
            "WHERE Ras_old.id='%i';",
            sql_table_field_no_tab("Ras_old","Name"),
            mn_selected_ra);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    if (sqlite3_column_value(res,0)==0)
    {
        name.Empty();
        level = -1;
    }
    else
    {
        name = CString(sqlite3_column_text(res,0));
        level = sqlite3_column_int(res,1);
    }
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 
}



CString	CDBInterfaceSQL::GetRADescription()
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_ra != -1); // No RA selected

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT %s FROM Ras_old WHERE id='%i';",
                sql_table_field_no_tab("Ras_old","Desc"),
                mn_selected_ra);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    CString desc = CString(sqlite3_column_text(res,0));
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 

    return desc;
}


int  CDBInterfaceSQL::FindRA(const CString& name, int nclass)
{
    ASSERT(mp_db); // Init not called
    ASSERT(nclass!=-1); // NO class selected

    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT Ras_Old.ID FROM Ras_Old "
        "INNER JOIN Classes_RasOld ON Ras_Old.ID=Classes_RasOld.RAS_Old_ID "
        "WHERE %s='%s' AND Classes_RasOld.Class_ID='%i';", 
        sql_table_field("Ras_old","Name"),
        sqlite3_escape_string(name),nclass);

    int ra = -1;
    if (sqlite3_step(res) == SQLITE_ROW)
    {
        ra = sqlite3_column_int(res, 0);
        ASSERT(sqlite3_step(res) == SQLITE_DONE); // found again?
    } else { ASSERT(false); }
    sqlite3_finalize(res); 

    return ra;
}


int  CDBInterfaceSQL::FindRANF(const CString& name, int nclass)
{
    ASSERT(mp_db); // Init not called
    ASSERT(nclass!=-1); // NO class selected 

    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT Rasnf.RASNF_ID FROM Rasnf "
        "INNER JOIN Classes_Rasnf ON Rasnf.RASNF_ID=Classes_Rasnf.RASNF_ID "
        "WHERE %s='%s' AND Classes_Rasnf.Class_ID='%i';", 
        sql_table_field("Rasnf","Name"),
        sqlite3_escape_string(name),nclass);

    int ra = -1;
    if (sqlite3_step(res) == SQLITE_ROW)
    {
        ra =  sqlite3_column_int(res, 0);
        ASSERT(sqlite3_step(res) == SQLITE_DONE); // found again?
    } else { ASSERT(false); }
    sqlite3_finalize(res); 

    return ra;
}


int CDBInterfaceSQL::GetRANFStatModif(int id, int level)
{
    ASSERT(mp_db); // Init not called

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT l1,l2,l3,l4,l5,l6,l7,l8,l9 FROM Rasnf WHERE RASNF_ID='%i';", id);

    int modif =0;
    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    if (level>0 && level < 10)    modif = _tstoi((char*)sqlite3_column_text(res, level-1));
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 

    return modif;
}



// ----------------------------------------------------
// RAs New Frontier
// ----------------------------------------------------
void  CDBInterfaceSQL::GetListOfRANF(IntArray& output)
{
    ASSERT(mp_db); // Init not called 
    ASSERT(m_class.id != -1); // no selected class 

    output.RemoveAll();

    sqlite3_stmt* res = sql_prepare( 
        "SELECT RASNF_ID FROM Classes_Rasnf WHERE CLASS_ID='%i';",  m_class.id);

    int rc;
    while ((rc=sqlite3_step(res)) == SQLITE_ROW)
    {
        output.Add( sqlite3_column_int(res, 0 ) );
    }

    ASSERT(output.GetCount()>0);

    sqlite3_finalize(res); 
}

//////////////////////////////////////////////////////////////////////////
void   CDBInterfaceSQL::SelectRANF(int id)
{
    ASSERT(mp_db); // Init not called
    ASSERT(m_class.id!=-1); // NO class selected (different classes may have different points ... maybe obsolete)

    mn_selected_raNF = id;

    #ifdef DEBUG
        sqlite3_stmt* res;
        res = sql_prepare( 
            "SELECT Rasnf.RASNF_ID FROM Rasnf "
            "INNER JOIN Classes_Rasnf ON Rasnf.RASNF_ID=Classes_Rasnf.RASNF_ID "
            "WHERE Rasnf.RASNF_ID='%i' AND Classes_Rasnf.Class_ID='%i';", 
            id, m_class.id);

        VERIFY(sqlite3_step(res) == SQLITE_ROW);
        VERIFY(sqlite3_step(res) == SQLITE_DONE);
        sqlite3_finalize(res); 
    #endif
}


/////////////////////////////////////////////////////////////////////////
CString   CDBInterfaceSQL::GetRAName(int id)
{
    ASSERT(mp_db); // Init not called

    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT %s FROM Ras_old WHERE Ras_old.ID='%i';", 
        sql_table_field("Ras_old","Name"),
        id);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    CString name = CString(sqlite3_column_text(res, 0));
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 

    return name;
}

//////////////////////////////////////////////////////////////////////////
CString   CDBInterfaceSQL::GetRANFName()
{
    return GetRANFName(mn_selected_raNF);
}

CString   CDBInterfaceSQL::GetRANFName(int id)
{
    ASSERT(mp_db); // Init not called

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT %s FROM Rasnf WHERE RASNF_ID='%i';", 
        sql_table_field("Rasnf","Name"),
        id);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    CString name = CString(sqlite3_column_text(res, 0));
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 

    return name;
}

CString     CDBInterfaceSQL::GetRRName(int realmrank)
{
    ASSERT(mp_db); // Init not called

    CString fn;
    switch (mn_selected_realm)
    {
        case R_ALBION:   fn = _T("Alb_Name"); break;
        case R_HIBERNIA: fn = _T("Hib_Name"); break;
        case R_MIDGARD:  fn = _T("Mid_Name"); break;
    }

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT %s FROM RR_Names WHERE Level='%i';", 
        sql_table_field_no_tab("RR_Names",fn),
        (realmrank/10)+1);

    CString name;
    if (sqlite3_step(res) == SQLITE_ROW)
    {
        name = CString(sqlite3_column_text(res, 0));
        ASSERT(sqlite3_step(res) == SQLITE_DONE);
    }

    sqlite3_finalize(res); 

    ASSERT(!name.IsEmpty()); 
    return name;
}

unsigned       CDBInterfaceSQL::GetRR_RPs(int realmrank)
{
    ASSERT(mp_db); // Init not called

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT RPS FROM RealmPoints WHERE RR='%i';", realmrank+10);

    unsigned rps=0;
    if (sqlite3_step(res) == SQLITE_ROW)
    {
        rps = sqlite3_column_int(res, 0);
        ASSERT(sqlite3_step(res) == SQLITE_DONE);
    }

    sqlite3_finalize(res); 

    return rps;
}

//////////////////////////////////////////////////////////////////////////
bool      CDBInterfaceSQL::IsFakeRANF(int id)
{ 
    ASSERT(mp_db); // Init not called

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT RASNF_ID FROM Rasnf WHERE RASNF_ID='%i' AND Isfake='true';",    id);

    bool isfake = sqlite3_step(res) == SQLITE_ROW;
    sqlite3_finalize(res); 

    return isfake;
}


//////////////////////////////////////////////////////////////////////////
int		CDBInterfaceSQL::GetRANFCost(int level, bool fake_points/*=false*/)
{
    ASSERT(mp_db); // Init not called 

    const int costtable[4][9]=
    {
        {1,1,2,3,3,5,5,7,7},
        {5,5,5,7,8,0,0,0,0},

        {1,3,6,10,14,0,0,0,0},
        {5,10,15,0,0,0,0,0,0}
    };

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT L4,L6, Type, Isfake FROM Rasnf WHERE RASNF_ID='%i';", mn_selected_raNF);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    const unsigned char* l4 = sqlite3_column_text(res,0);
    const unsigned char* l6 = sqlite3_column_text(res,1);
    int ratype = sqlite3_column_int(res,2);
    int isfake = sqlite3_column_int(res,3);
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 

    if (ratype==3) return 0;
    if (ratype==0 && (l6==NULL || l6[0]==0))  ratype=2;
    if (ratype==1 && (l4==NULL || l4[0]==0))  ratype=3;
    ASSERT(ratype>=0 && ratype<5);
    ASSERT(level<9);

    if (!fake_points && isfake) return 0;
    return costtable[ratype][level];
}



//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::GetRAInfoNF(string& shortname, string& reuse, int& ratype, int& type)
{
    ASSERT(mp_db); // Init not called
    ASSERT(mn_selected_raNF != -1); // No RA selected

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT Short, reuse, Type, Art FROM Rasnf WHERE RASNF_ID='%i';", 
        mn_selected_raNF);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    shortname  = CString(sqlite3_column_text(res, 0));
    reuse = CString(sqlite3_column_text(res, 1));
    ratype = sqlite3_column_int(res,2);
    type = sqlite3_column_int(res,3);
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 


    int reuse_nr = atoi(reuse.c_str());
    if (reuse_nr==-1)
    {
        if (mstr_current_language=="de") reuse="s.Effekt";
        else reuse="s.effect";
    }


    if (ratype==0 || reuse_nr==0) reuse.clear();
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::GetRALevelsNF(std::string l[9])
{

    ASSERT(mp_db); // Init not called
    ASSERT(mn_selected_raNF != -1); // No RA selected

    sqlite3_stmt* res;
//    res = sql_prepare( "SELECT L1,L2,L3,L4,L5,L6,L7,L8,L9 Type, Art FROM Rasnf WHERE RASNF_ID='%i';", 
    res = sql_prepare( "SELECT L1,L2,L3,L4,L5,L6,L7,L8,L9 FROM Rasnf WHERE RASNF_ID='%i';", 
        mn_selected_raNF);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);

    for (int t=0;t<9;++t)
        l[t]  = CString(sqlite3_column_text(res, t));

        /*l[0]  = CString(sqlite3_column_text(res, 0));
    l[1]  = CString(sqlite3_column_text(res, 1));
    l[2]  = CString(sqlite3_column_text(res, 2));

    if (sqlite3_column_int(res,5)==0)
    {
        l[3]  = CString(sqlite3_column_text(res, 3));
        l[4]  = CString(sqlite3_column_text(res, 4));
    }
    else
    {
        l[3].clear();
        l[4].clear();
    }*/


    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 
}

CString	CDBInterfaceSQL::GetRADescriptionNF()
{
    ASSERT(mp_db); // Init not called
    ASSERT(mn_selected_raNF != -1); // No RA selected

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT %s FROM Rasnf WHERE RASNF_ID='%i';", 
        sql_table_field_no_tab("Rasnf","TEXT"),
        mn_selected_raNF);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    CString desc = CString(sqlite3_column_text(res, 0));
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 

    return desc;
}





// ----------------------------------------------------
// Abilities
// ----------------------------------------------------
void	CDBInterfaceSQL::GetListOfAbilities(CStringArray& name, IntArray& level,IntArray& type)
{
    ASSERT(mp_db); // Init not called 
	ASSERT(m_class.id != -1); // No class selected

	name.RemoveAll();
	level.RemoveAll();
	type.RemoveAll();

    // Rest
    sqlite3_stmt* res = sql_prepare( 
        "SELECT %s, Classes_Abilities.Level, Ability_Desc.Type, Stylelines.Base_Attribute  "
        "FROM Ability_Desc "
        "INNER JOIN Classes_Abilities ON Ability_Desc.ID = Classes_Abilities.ABILITY_ID "
        "LEFT JOIN Stylelines ON %s = %s "
        "WHERE Classes_Abilities.CLASS_ID='%i' "
        "GROUP BY %s;",
        sql_table_field("Ability_Desc","Name"),
        sql_table_field("Stylelines","Name"),sql_table_field("Ability_Desc","Name"),
        m_class.id, sql_table_field("Ability_Desc","Name"));

    int rc;
    while ((rc=sqlite3_step(res)) == SQLITE_ROW)
    {
        name.Add(CString(sqlite3_column_text(res, 0)));
        level.Add(sqlite3_column_int(res, 1));
        int temp = sqlite3_column_int(res, 3);
        if (temp>0)
            type.Add(7 + (temp<<4));
        else
            type.Add(sqlite3_column_int(res, 2));
    }
    sqlite3_finalize(res); 


    // styles
    res = sql_prepare( 
        "SELECT %s, Classes_Stylelines.Level, Stylelines.Base_Attribute "
        "FROM Stylelines "
        "INNER JOIN Classes_Stylelines ON Stylelines.STYLELINE_ID = Classes_Stylelines.STYLELINE_ID "
        "WHERE Classes_Stylelines.CLASS_ID='%i';",
        sql_table_field("Stylelines","Name"),m_class.id);

    while ((rc=sqlite3_step(res)) == SQLITE_ROW)
    {
        name.Add(CString(sqlite3_column_text(res, 0)));
        level.Add(sqlite3_column_int(res, 1));
        type.Add(1 + (sqlite3_column_int(res, 2)<<4));
    }
    sqlite3_finalize(res); 


    // spells
    res = sql_prepare( 
        "SELECT %s, Classes_Spelllines.Level, %s FROM Spelllines "
        "INNER JOIN Classes_Spelllines ON Spelllines.SPELLLINE_ID = Classes_Spelllines.SPELLLINE_ID "
        "WHERE Classes_Spelllines.CLASS_ID='%i';",
        sql_table_field("Spelllines","Name_Base"),
        sql_table_field("Spelllines","Name_Spec"),
        m_class.id);

    while ((rc=sqlite3_step(res)) == SQLITE_ROW)
    {
        name.Add(CString(sqlite3_column_text(res, 0)));
        level.Add(sqlite3_column_int(res, 1));
        type.Add(1);

        CString spec = CString(sqlite3_column_text(res, 2));
        if (!spec.IsEmpty())
        {
            name.Add(spec);
            level.Add(5);
            type.Add(2);
        }
    }
    sqlite3_finalize(res); 



    // SORT
    for (int t=0;t<name.GetCount()-1;t++)
        for (int t2=t+1;t2<name.GetCount();t2++)
        {
            // sort by: a) Banner b) level c) name
            if ((type[t2]==5) || (type[t]!=5) && (level[t]>level[t2] || (level[t]==level[t2] && name[t]>name[t2])))
            {
                CString temp = name[t];
                name[t] = name[t2];
                name[t2] = temp;

                int l = level[t];
                level[t] = level[t2];
                level[t2] = l;

                int tr = type[t];
                type[t] = type[t2];
                type[t2] = tr;
            }
        }
}


//////////////////////////////////////////////////////////////////////////
CString	CDBInterfaceSQL::GetAbilityDesc(const CString&str, bool style)
{
    ASSERT(mp_db); // Init not called 

    sqlite3_stmt* res;
    res = sql_prepare( 
        "SELECT %s FROM Ability_Desc "
        "WHERE %s='%s' %s;",
        sql_table_field_no_tab("Ability_Desc","Desc"),
        sql_table_field_no_tab("Ability_Desc","Name"),
        sqlite3_escape_string(str),
        style?"AND Type='6'":"");


    CString eff;
    if (sqlite3_step(res) == SQLITE_ROW)
    {
        eff = CString(sqlite3_column_text(res,0));
        ASSERT(sqlite3_step(res) == SQLITE_DONE);
    }
    sqlite3_finalize(res); 

    return eff;
}




// ----------------------------------------------------
// MasterLevels
// ----------------------------------------------------
CString	CDBInterfaceSQL::GetMasterTrack(int path)
{
    ASSERT(mp_db); // Init not called 
	ASSERT(m_class.id != -1); // No class selected
    ASSERT(path==0||path==1);

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT ML1.%s, ML2.%s FROM Classes "
                        "INNER JOIN Masterlines AS ML1 ON Classes.ML_1 = ML1.Masterline_ID " 
                        "INNER JOIN Masterlines AS ML2 ON Classes.ML_2 = ML2.Masterline_ID "
                        "WHERE Classes.CLASS_ID='%i'",
                        sql_table_field_no_tab("Masterlines","Name"),
                        sql_table_field_no_tab("Masterlines","Name"),
                        m_class.id);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    CString name = CString(sqlite3_column_text(res, path));
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 

    return name;
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::SelectMasterTrack(const CString& str_ma)
{
    ASSERT(mp_db); // Init not called 

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT Masterline_ID FROM Masterlines WHERE %s='%s';",
        sql_table_field_no_tab("Masterlines","Name"),
        sqlite3_escape_string(str_ma));

    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    mn_selected_mastertrack = sqlite3_column_int(res, 0);
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::GetMasterLevels(CStringArray& results)
{
    ASSERT(mp_db); // Init not called 
	ASSERT(mn_selected_mastertrack != -1); // No Track selected

    results.RemoveAll();

    sqlite3_stmt* res = sql_prepare( 
        "SELECT %s FROM Masterlevel WHERE Masterline_ID='%i' ORDER BY Level",
        sql_table_field("Masterlevel","L_Name"),  mn_selected_mastertrack);


    int rc;
    while ((rc=sqlite3_step(res)) == SQLITE_ROW)
    {
        results.Add(CString(sqlite3_column_text(res, 0)));
    }

    ASSERT(results.GetCount()>0);

    sqlite3_finalize(res); 
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::GetMasterLevelInfo(int level, CString&target, int& timer)
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_mastertrack != -1); // No Track selected

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT Target, Shared_Timers FROM Masterlevel WHERE Masterline_ID='%i' AND Level='%i';",
                 mn_selected_mastertrack, level);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    target = CString(sqlite3_column_text(res, 0));
    timer = sqlite3_column_int(res, 1);
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 
}


//////////////////////////////////////////////////////////////////////////
CString	CDBInterfaceSQL::GetMasterDescription(int level)
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_mastertrack != -1); // No Track selected

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT %s, Target, Cast_Time, Duration, Recast_Time, Range_Radius, %s "
            "FROM Masterlevel WHERE Masterline_ID='%i' AND Level='%i';",
            sql_table_field("Masterlevel","L_Name"),
            sql_table_field("Masterlevel","Description"),
            mn_selected_mastertrack, level);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);

    // build description
    CString desc;
    desc =  _T("<al><b>")           + CString(sqlite3_column_text(res, 0)) + _T("</b><br>");
    desc += _T("Target: <b>")       + CString(sqlite3_column_text(res, 1)) + _T("</b><br>");
    desc += _T("<al>Cast time: <b>")+ CString(sqlite3_column_text(res, 2)) + _T("</b> ");
    desc += _T("Duration: <b>")     + CString(sqlite3_column_text(res, 3)) + _T("</b>  ");
    desc += _T("Recast: <b>")       + CString(sqlite3_column_text(res, 4)) + _T("</b>  ");
    desc += _T("Radius/Range: <b>") + CString(sqlite3_column_text(res, 5)) + _T("</b><br><hr=100%><br>");
    desc += CString(sqlite3_column_text(res, 6));
    desc += _T("<br><hr=100%><br>");

    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res);


    return desc;
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::GetMasterQuests(int level, CStringArray& names, IntArray& type)
{
    ASSERT(mp_db); // Init not called

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT %s, Gruppe FROM MasterQuest WHERE Masterlevel='%i';", 
        sql_table_field_no_tab("MasterQuest","Name"),
        level);

    while (sqlite3_step(res) == SQLITE_ROW)
    {
        names.Add(CString(sqlite3_column_text(res, 0)));
        type.Add(sqlite3_column_int(res, 1));
    }
    sqlite3_finalize(res); 
}





// ----------------------------------------------------
// Champion-Levels
// ----------------------------------------------------
void	CDBInterfaceSQL::GetListOfChampTrainers(CStringArray& ways, IntArray&counts)
{
    ASSERT(mp_db); // Init not called 
	ASSERT(m_class.id != -1);	// need class

	ways.RemoveAll();
	counts.RemoveAll();


    
    sqlite3_stmt* res;
    res = sql_prepare(
        "SELECT  %s FROM Classes " // Classes.Name_EN,
         "INNER JOIN Classes AS Classes_1 ON Classes.Realm = Classes_1.Realm " 
         "INNER JOIN ChampLines ON Classes_1.Base_Class_ID = ChampLines.Base_Class "
         "INNER JOIN ChampSpells ON ChampLines.Lvl_1 = ChampSpells.ChampSpell_ID "
         "INNER JOIN Base_Classes ON Base_Classes.Base_Class_ID=ChampLines.Base_Class "
        "WHERE (((Classes.CLASS_ID)='%i') AND ((Classes_1.Base_Class_ID)<>Classes.Base_Class_ID)) "
        "GROUP BY Classes.Name_EN, ChampLines.Base_Class, ChampSpells.Name_EN "
        "ORDER BY ChampLines.Base_Class;",
        sql_table_field("Base_Classes","Base_Name"),
        m_class.id);

    CString last;
    while (sqlite3_step(res) == SQLITE_ROW)
    {
        CString next = CString(sqlite3_column_text(res, 0));
        if (last!=next)
        {
            ways.Add(next);
            counts.Add(1);
            last=next;
        }
        else counts[counts.GetCount()-1]++;
    }
    sqlite3_finalize(res); 
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::GetListOfChampSpells(const CString& na ,int nr,IntArray&ids)
{	
    ASSERT(mp_db); // Init not called
    ASSERT(nr>=0 && nr <=5);
    ASSERT(mn_selected_realm != -1);

    sqlite3_stmt* res;
    res = sql_prepare( 
        "select ChampLines.Lvl_1, ChampLines.Lvl_2, ChampLines.Lvl_3, ChampLines.Lvl_4, ChampLines.Lvl_5 FROM ChampLines " 
        "INNER JOIN Base_Classes ON Base_Classes.Base_Class_ID=ChampLines.Base_Class "
        "INNER JOIN Classes ON Classes.Base_Class_ID=ChampLines.Base_Class "
        "WHERE %s='%s' AND (ChampLines.Lvl_1 %% 10)=%i AND Classes.Realm='%i';",
        sql_table_field("Base_Classes","Base_Name"),
        sqlite3_escape_string(na),
        nr,
        mn_selected_realm);
    // result will have multiple lines


    VERIFY(sqlite3_step(res) == SQLITE_ROW);

        ids.Add(sqlite3_column_int(res, 0));
        ids.Add(sqlite3_column_int(res, 1));
        ids.Add(sqlite3_column_int(res, 2));
        ids.Add(sqlite3_column_int(res, 3));
        ids.Add(sqlite3_column_int(res, 4));


    sqlite3_finalize(res);
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::GetChampSpell(int id, CString&na,CString&ta,CStringArray&va,int&ni)
{
    ASSERT(mp_db); // Init not called 


    sqlite3_stmt* res;
    res = sql_prepare( 
        "select %s, Color, IsStyle, %s, %s, %s, %s, %s, %s, %s "
        "FROM ChampSpells WHERE ChampSpell_ID='%i';",
        sql_table_field_no_tab("ChampSpells","Name"),
        sql_table_field_no_tab("ChampSpells","L1"),
        sql_table_field_no_tab("ChampSpells","L2"),
        sql_table_field_no_tab("ChampSpells","L3"),
        sql_table_field_no_tab("ChampSpells","L4"),
        sql_table_field_no_tab("ChampSpells","L5"),
        sql_table_field_no_tab("ChampSpells","L6"),
        sql_table_field_no_tab("ChampSpells","L7"),
        id);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    na = CString(sqlite3_column_text(res,0));
    ni = sqlite3_column_int(res, 1);
    ta = sqlite3_column_int(res, 2)?"Style":"Spell";
    va.Add( CString(sqlite3_column_text(res,3)));
    va.Add( CString(sqlite3_column_text(res,4)));
    va.Add( CString(sqlite3_column_text(res,5)));
    va.Add( CString(sqlite3_column_text(res,6)));
    va.Add( CString(sqlite3_column_text(res,7)));
    va.Add( CString(sqlite3_column_text(res,8)));
    va.Add( CString(sqlite3_column_text(res,9)));

    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res);
}



//////////////////////////////////////////////////////////////////////////
CString			CDBInterfaceSQL::GetDBState()
{
    if (!mp_db)		return _T("not init");

#ifdef ONLY_US_DB
    CString res(_T("(")+mstr_current_language+ _T("/us) ->"));
#else
    CString res(_T("(")+mstr_current_language+ _T("/")+(mb_old_version?_T("eu"):_T("us")) + _T(") ->"));
#endif
    CString temp;

    // realm
    if (mn_selected_realm<0)	return _T("no realm");

    temp.Format(_T("%s (%i)"),GetRealmName(mn_selected_realm),mn_selected_realm);
    res += temp;

	// class
	if (m_class.id<0)
	{
		return res+_T("/no class");
	}

	temp.Format(_T("%s (%i) %s"),GetClassName(m_class.id),m_class.id,
							IsClassFemaleOnly()?"female":"");
	res += _T("/")+temp;

	// race
	if (mn_selected_race>=0)
	{
		temp.Format(_T("%s (%i)"),GetRaceName(mn_selected_race),mn_selected_race);
		res += _T("/")+temp;
	}

    res += _T("\n");

    return res;
}




//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::EditAddRA(int realm, int type, 
          const char* name_en, const char* name_de, const char*name_fr,  
          const char* short_desc, bool active,
          const char* desc_en, const char* desc_de, const char* desc_fr, 
          const char** levels, int reuse)
{
    ASSERT(mp_db); // Init not called 

    // find free ID
    sqlite3_stmt* res;
    res = sql_prepare("select max(RASNF_ID)+1 from RASnf;");

    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    int ra_id = sqlite3_column_int(res, 0);
    VERIFY(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res);

    // add new RA
    sql_execute(
      "INSERT INTO Rasnf "
      "( RASNF_ID, Type, Name_EN, Name_DE, Name_FR, Short, Art, Text_EN, Text_DE,Text_FR,"
      " Reuse, L1, L2, L3, L4, L5, Isfake )"
      " VALUES "
      "( %i, %i, '%s', '%s', '%s', '%s', %i, '%s', '%s', '%s',"
      " %i, '%s', '%s', '%s', '%s', '%s', 'True');",
      ra_id, type, name_en, name_de?name_de:name_en, name_fr?name_fr:name_en, short_desc?short_desc:"", active?2:1,
      desc_en?desc_en:"", desc_de?desc_de:(desc_en?desc_en:""), desc_fr?desc_fr:(desc_en?desc_en:""), 
      reuse, levels?levels[0]:"", levels?levels[1]:"", levels?levels[2]:"", levels?levels[3]:"", levels?levels[4]:"" ); 

    // append to classes
    sql_execute(
        "INSERT INTO Classes_Rasnf (CLASS_ID, RASNF_ID) "
        "SELECT Class_id, '%i' FROM Classes WHERE Realm='%i';",
         ra_id, realm );
}



//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::EditAddRA(const char* class_id,int type,const char* name, const char* short_desc, bool active,const char* desc, const char** levels, const char* reuse)
{
    ASSERT(false);//SQL
    ASSERT(mp_db); // Init not called 
    /*
	int id = mc_classes.GetClassID(class_id);
	mc_rasnf.InsertRA(id,type,name,short_desc,active,desc,levels,reuse);
    */
}


//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::EditAddClassLine(int realm, INT_PTR id)
{
    ASSERT(false);//SQL
    ASSERT(mp_db); // Init not called 
    /*
	CStringArray names;
	mc_classes.GetClasses(names,realm);

	for (int t=0;t<names.GetCount();t++)
		EditAddClassLine(names[t],id);
      */
}

//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::EditAddClassLine(const TCHAR* class_id, INT_PTR id)
{
    ASSERT(false);//SQL
    ASSERT(mp_db); // Init not called 
    /*
	int cid = mc_classes.GetClassID(class_id);
	mc_classes.InsertSpellLine(cid,(int)id);
	mc_abilities.AddSpellLevel(class_id,0);
    */
}

//////////////////////////////////////////////////////////////////////////
INT_PTR		CDBInterfaceSQL::EditAddSpellLine(const TCHAR* skill,const TCHAR* base,const TCHAR* spec)
{
    ASSERT(false);//SQL
    return 0;
    ASSERT(mp_db); // Init not called 
    /*
	return mc_spelllines.InsertLine(skill,base,spec);
    */
}

//////////////////////////////////////////////////////////////////////////
int		CDBInterfaceSQL::EditAddSpellCat(INT_PTR spellline_id, bool base, const TCHAR*name, const TCHAR* desc)
{
    ASSERT(false);//SQL
    return 0;
    ASSERT(mp_db); // Init not called 
    /*
	int id = mc_spellcats.InsertCat(name, desc);
	mc_spelllines.InsertCat((int)spellline_id, base, id);
	return id;
    */
}

//////////////////////////////////////////////////////////////////////////
void	CDBInterfaceSQL::EditAddSpell(INT_PTR spell_cat_id, const TCHAR* name, int level,const TCHAR* target,const TCHAR* times,const TCHAR* range,const TCHAR* costs,const TCHAR* dam,const TCHAR* damtype)
{
    ASSERT(false);//SQL
    ASSERT(mp_db); // Init not called 
    /*
	int id = mc_spells.Insert(name, level,target,times,range,costs,dam,damtype);
	mc_spellcats.InsertSpell((int)spell_cat_id,id);
    */
}

//////////////////////////////////////////////////////////////////////////
mstring		CDBInterfaceSQL::MoraGetClassName()
{
    ASSERT(m_class.id != -1);
    return m_class.mora_ID;
}


//////////////////////////////////////////////////////////////////////////
CString		CDBInterfaceSQL::MoraGetRaceName()
{
    ASSERT(mp_db); // Init not called 
    ASSERT(mn_selected_race != -1);

    sqlite3_stmt* res;
    res = sql_prepare( "SELECT MORA_ID FROM Race WHERE RACE_ID='%i';", mn_selected_race);

    VERIFY(sqlite3_step(res) == SQLITE_ROW);
    CString name = CString(sqlite3_column_text(res, 0));
    ASSERT(sqlite3_step(res) == SQLITE_DONE);
    sqlite3_finalize(res); 

    return name;
}

